/*
REWRITTEN FROM SCRATCH BY PUSSYWIZARD, IT OWNS NOW!
*/

#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "violet_hold.h"
#include "PassiveAI.h"

enum Yells
{
    SAY_AGGRO                                   = 0,
    SAY_SLAY                                    = 1,
    SAY_DEATH                                   = 2,
    SAY_SPAWN                                   = 3,
    SAY_SHIELD                                  = 4,
    SAY_WHISPER                                 = 5
};

enum eSpells
{
	SPELL_SHROUD_OF_DARKNESS_N						= 54524,
	SPELL_SHROUD_OF_DARKNESS_H						= 59745,
	SPELL_VOID_SHIFT_N								= 54361,
	SPELL_VOID_SHIFT_H								= 59743,
	SPELL_SUMMON_VOID_SENTRY						= 54369,
	SPELL_SUMMON_VOID_SENTRY_BALL					= 58650,

	//SPELL_ZURAMAT_ADD_2_N							= 54342,
	//SPELL_ZURAMAT_ADD_2_H							= 59747,
};

#define NPC_VOID_SENTRY_BALL						29365
#define SPELL_SHROUD_OF_DARKNESS					DUNGEON_MODE(SPELL_SHROUD_OF_DARKNESS_N, SPELL_SHROUD_OF_DARKNESS_H)
#define SPELL_VOID_SHIFT							DUNGEON_MODE(SPELL_VOID_SHIFT_N, SPELL_VOID_SHIFT_H)

enum eEvents
{
	EVENT_SPELL_SHROUD_OF_DARKNESS = 1,
	EVENT_SPELL_VOID_SHIFT,
	EVENT_SPELL_SUMMON_VOID_SENTRY,
};

class boss_zuramat : public CreatureScript
{
public:
	boss_zuramat() : CreatureScript("boss_zuramat") { }

	CreatureAI* GetAI(Creature* pCreature) const
	{
		return new boss_zuramatAI (pCreature);
	}

	struct boss_zuramatAI : public ScriptedAI
	{
		boss_zuramatAI(Creature *c) : ScriptedAI(c), summons(me)
		{
			pInstance = c->GetInstanceScript();
		}

		InstanceScript* pInstance;
		EventMap events;
		SummonList summons;

		void Reset()
		{
			events.Reset();
			summons.DespawnAll();
		}

		void EnterCombat(Unit* /*who*/)
		{
            Talk(SAY_AGGRO);
			DoZoneInCombat();
			events.Reset();
			events.RescheduleEvent(EVENT_SPELL_SHROUD_OF_DARKNESS, urand(5000,7000));
			events.RescheduleEvent(EVENT_SPELL_VOID_SHIFT, urand(23000,25000));
			events.RescheduleEvent(EVENT_SPELL_SUMMON_VOID_SENTRY, 10000);
			if (pInstance)
				pInstance->SetData(DATA_ACHIEV, 1);
		}

		void UpdateAI(uint32 diff)
		{
			if (!UpdateVictim())
				return;

			events.Update(diff);

			if (me->HasUnitState(UNIT_STATE_CASTING))
				return;

			switch(events.GetEvent())
			{
				case 0:
					break;
				case EVENT_SPELL_SHROUD_OF_DARKNESS:
					me->CastSpell(me, SPELL_SHROUD_OF_DARKNESS, false);
					Talk(SAY_SHIELD);
					events.RepeatEvent(20000);
					break;
				case EVENT_SPELL_VOID_SHIFT:
					if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, true))
					{
						me->CastSpell(target, SPELL_VOID_SHIFT, false);
						me->MonsterWhisper("Gaze... into the void.", target->ToPlayer(), false);
					}
					events.RepeatEvent(urand(18000,22000));
					break;
				case EVENT_SPELL_SUMMON_VOID_SENTRY:
					me->CastSpell((Unit*)NULL, SPELL_SUMMON_VOID_SENTRY, false);
					events.RepeatEvent(12000);
					break;
			}

			DoMeleeAttackIfReady();
		}

		void JustDied(Unit* /*killer*/)
		{
			summons.DespawnAll();
            Talk(SAY_DEATH);
			if (pInstance)
				pInstance->SetData(DATA_BOSS_DIED, 0);
		}

        void KilledUnit(Unit * victim)
        {
			if (victim && victim->GetGUID() == me->GetGUID())
                return;

            Talk(SAY_SLAY);
        }

		void JustSummoned(Creature* pSummoned)
		{
			if (pSummoned)
			{
				summons.Summon(pSummoned);
				pSummoned->SetPhaseMask(16, true);
				if (pInstance)
					pInstance->SetData64(DATA_ADD_TRASH_MOB, pSummoned->GetGUID());
			}
		}

		void SummonedCreatureDespawn(Creature *pSummoned)
		{
			if (pSummoned)
			{
				summons.Despawn(pSummoned);
				if (pSummoned->IsAIEnabled)
					pSummoned->AI()->DoAction(-1337);
				if (pInstance)
					pInstance->SetData64(DATA_DELETE_TRASH_MOB, pSummoned->GetGUID());
			}
		}

		void MoveInLineOfSight(Unit* /*who*/) {}

		void EnterEvadeMode()
		{
			ScriptedAI::EnterEvadeMode();
			events.Reset();
			me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
			if (pInstance)
				pInstance->SetData(DATA_FAILED, 1);
		}
	};
};

class npc_vh_void_sentry : public CreatureScript
{
public:
	npc_vh_void_sentry() : CreatureScript("npc_vh_void_sentry") { }

	CreatureAI* GetAI(Creature* pCreature) const
	{
		return new npc_vh_void_sentryAI (pCreature);
	}

	struct npc_vh_void_sentryAI : public NullCreatureAI
	{
		npc_vh_void_sentryAI(Creature *c) : NullCreatureAI(c)
		{
			pInstance = c->GetInstanceScript();
			SummonedGUID = 0;
			checkTimer = 5000;
			//me->CastSpell(me, SPELL_SUMMON_VOID_SENTRY_BALL, true);
			if (Creature* pSummoned = me->SummonCreature(NPC_VOID_SENTRY_BALL, *me, TEMPSUMMON_TIMED_DESPAWN, 300000))
			{
				pSummoned->SetPhaseMask(1, true);
				SummonedGUID = pSummoned->GetGUID();
				pInstance->SetData64(DATA_ADD_TRASH_MOB, pSummoned->GetGUID());
			}
		}

		InstanceScript* pInstance;
		uint64 SummonedGUID;
		uint16 checkTimer;

		void DoAction(int32 a)
		{
			if (a == -1337)
				if (Creature* c = pInstance->instance->GetCreature(SummonedGUID))
					c->DespawnOrUnsummon();
		}

		void JustDied(Unit* /*killer*/)
		{
			if (pInstance)
			{
				pInstance->SetData(DATA_ACHIEV, 0);
				if (Creature* c = pInstance->instance->GetCreature(SummonedGUID))
					c->DespawnOrUnsummon();
			}
			me->DespawnOrUnsummon(5000);
		}

		void SummonedCreatureDespawn(Creature *pSummoned)
		{
			if (pSummoned)
				pInstance->SetData64(DATA_DELETE_TRASH_MOB, pSummoned->GetGUID());
		}

		void UpdateAI(uint32 diff)
		{
			if (checkTimer <= diff)
			{
				checkTimer = 5000;
				bool good = false;
				if (me->IsSummon())
					if (Unit* s = me->ToTempSummon()->GetSummoner())
						if (s->IsAlive())
							good = true;
				if (!good)
					Unit::Kill(me, me);
			}
			else
				checkTimer -= diff;
		}
	};
};

void AddSC_boss_zuramat()
{
	new boss_zuramat();
	new npc_vh_void_sentry();
}
